// 定义字符串
let str: string = "hello";
let str2: string;
str2 = "hi";

// 自动类型推断
let str3 = "hihi";

// 定义数字
let num1: number = 1;
num1 = 4;

// 定义布尔值
let done: boolean = true;
done = false;

// 定义undefined
let udf: undefined = undefined;

// 定义null
let nl: null = null;

// 联合类型(有可能存在多种类型的情况)
let a: number | boolean | string = 1;
a = true;
a = "3";

// any类型(表示任意类型)
let b: any = 4;
b = [1, 3, "4"];

// 数组类型
let arr1: number[] = [1, 2, 3, 4];
let arr2: Array<string> = ["1", "2", "3"];
let arr3: (number | boolean)[] = [1, 2, true];
let arr4: Array<number | boolean> = [1, 2, true];
let arr5: Array<number | string | number[]> = [1, "3", [1, 2, 3]];
let arr6: Array<any> = [1, "3", [1, 2, 3]];
let arr7: any = [1, "3", [1, 2, 3]];

// 元组类型Tuple
// 元组就是一种特定的数组，规定了数组的长度，并且规定了数组的每一项的类型
let tuple1: [number, string] = [4, "6"];
// tuple1.split("") // 不能使用不是这个类型的方法
// tuple1[2] // 不能进行越界访问

// 对象类型
// 接口 interface，我们可以自己定义一种类型
interface ObjType {
  // 没有小括号，分号
  name: string;
  age: number;
  // 问号表示可选参数
  likes?: number[];
  // 索引签名
  [propname: string]: any;
}
let obj1: ObjType = {
  name: "junjun",
  age: 25,
  a: 3,
  b: "4",
  c: true,
};
obj1.likes = [299, 399, 699, 1299];

// 对象练习
interface ItemType {
  id: number;
  name: string;
}
let arr8: ItemType[] = [
  {
    id: 1,
    name: "zhangsan",
  },
  {
    id: 2,
    name: "lisi",
  },
];

interface Obj2Type {
  id: number;
  name: string;
  children?: Obj2Type[];
}
let obj2: Obj2Type = {
  id: 1,
  name: "zhangsan",
  children: [
    {
      id: 2,
      name: "zhangsi",
    },
    {
      id: 3,
      name: "zhangwu",
    },
  ],
};

// 枚举类型 Enum
// 有点像对象，枚举类型是可以通过key找value，也可以通过value找key
enum Color {
  Red = 5,
  Green = 10,
  Blue,
}
// let g: Color = Color.Green;
// console.log(g);
// let colorname: string = Color[10];
// console.log(colorname);

// 函数类型
// 返回值类型
function add(): string {
  return "5";
}
// 函数的参数是没有类型推断的
// 问号表示可选参数
// 必选参数要写在可选参数的前面
function add2(x: number, y?: string): string {
  return y ? x + y : x + "";
}
add2(3, "5");
add2(3);

// void只用于函数，表示没有返回值
function add3(x: number): void {
  console.log(x);
}
// add3(4);

// never表示从不，只用于函数，死循环或者报错
// function add4(): never {
//   while (true) {}
// }
// function add5(): never {
//   throw new Error();
// }

let add6: (x: number, y: number) => number = (x: number, y: number): number => {
  return x + y;
};
add6(3, 4);

// 泛型类型
// 相当于是函数的类型的形参
function fn<T>(x: T, y: T) {
  return `${x}${y}`;
}
// number是实参
fn<number>(4, 5);
// const num = ref<number>(7);

// 类
interface ObjType2 {
  name: string;
}
class Animal {
  constructor(obj: ObjType2) {
    // console.log(456);
    this.names = obj.name;
  }
  names: string = "dog";
  sayName(): string {
    return this.names;
  }
}

class Cat extends Animal {
  // 每一个类里面都有一个constructor函数
  // constructor函数是在这个类被实例化的时候自动调用的
  constructor(obj: ObjType2) {
    // super函数一旦调用，就相当于调用了父类的constructor
    super(obj);
    // console.log(123);
  }
}

const cat = new Cat({
  name: "cat",
});

console.log(cat.sayName());
